package com.open4cn.simulator.core.connector.serialport;

import com.open4cn.simulator.core.exception.UnableToProcessException;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author yinxiaopeng
 * @version 1.0.0
 * @company 致景科技
 * @department 飞梭BU/研发
 * @description
 * @Email yinxiaopeng@zj.tech
 * @date 2022-06-11 15:46
 */
public class SerialPortHandlerContext {
    private List<SerialPortHandler> handlers = new ArrayList<>();
    private SerialPortChannel serialPortChannel;
    // a->b->c->A->B->C
    private SerialPortHandler header;
    private SerialPortHandler tail;
    private SerialPortHandler current;

    public SerialPortHandlerContext(SerialPortChannel serialPortChannel) {
        this.serialPortChannel = serialPortChannel;
    }


    /**
     * 逐级向内输入
     * a->b->c
     *
     * @param msg
     */
    public void fireRead(Object msg) {
        if (null != current && current.hasNext()) {
            current = current.next();
            if (current instanceof ByteToMessageDecoder) {
                ((ByteToMessageDecoder) current).decode(this, msg);
                return;
            }
            if (current instanceof SerialPortInboundHandler) {
                ((SerialPortInboundHandler) current).serialPortRead(this, msg);
                return;
            }

            if (current instanceof MessageToByteEncoder) {
                ((MessageToByteEncoder) current).encode(this, msg);
                return;
            }

            if (current instanceof SerialPortOutboundHandler) {
                ((SerialPortOutboundHandler) current).write(this, msg);
                return;
            }
        }

    }


    /**
     * 逐级向外输出
     * A->B->C
     *
     * @param msg
     */
    public void write(Object msg) {
        // 到达最后一个节点
        if (null != tail && tail.equals(current)) {
            reset();
            if (null == msg) {
                serialPortChannel.write(new byte[0]);
                return;
            }
            if (msg instanceof byte[]) {
                serialPortChannel.write((byte[]) msg);
                return;
            }
            if (!(msg instanceof byte[])) {
                serialPortChannel.write(msg.toString().getBytes(StandardCharsets.US_ASCII));
                return;
            }
            return;
        }

        if (null != current && current.hasNext()) {
            current = current.next();
            if (current instanceof SerialPortInboundHandler) {
                throw new UnableToProcessException("handler类型顺序错误");
            }
            if (current instanceof MessageToByteEncoder) {
                ((MessageToByteEncoder) current).encode(this, msg);
                return;
            }

            if (current instanceof SerialPortOutboundHandler) {
                ((SerialPortOutboundHandler) current).write(this, msg);
                return;
            }
        }
    }

    /**
     * 添加节点
     *
     * @param serialPortHandler
     */
    public void addLast(SerialPortHandler serialPortHandler) {
        handlers.add(serialPortHandler);
        if (null == header) {
            header = serialPortHandler;
            current = header;
        }
        if (null != tail) {
            tail.next(serialPortHandler);
        }
        tail = serialPortHandler;
    }

    public SerialPortHandler header() {
        return header;
    }


    /**
     * 重置current指针位置
     */
    public void reset() {
        current = header;
    }
}
